/**@file     app.c 
 * @brief	Application中任务实现
 * 
 * @author SealedGhost
 */
 
#ifdef USE_UCOS


#include "app.h" 
#include "debug.h"

#ifdef USE_UCOS
#include "ucos_ii.h"
#endif



#ifdef USE_FREERTOS
#include "FreeRTOS.h"
#include "task.h"
#endif




#include "string_util.h"
#include "usart.h"

#include "at.h"
#include "m26.h"


/** @addtogroup
 *   
 *   @{
 */


/**  Define task priority  */
#define TASK_PRIO_ATHandler            2
#define TASK_PRIO_Acquire              3


/**  Define task stack size  */
#define TASK_STK_SIZE_ATHandler      80
#define TASK_STK_SIZE_Acquire        80

/**  Create task stack  */
static OS_STK ATHandlerTaskStk[TASK_STK_SIZE_ATHandler];
static OS_STK AcquireTaskStk[TASK_STK_SIZE_Acquire];

OS_EVENT* SemUsart1Rx;

void AcquireTask(void* arg);
void ATHandler(void* arg);

void setConfiguration(void);
int  configGSM(void);
int  configGPRS(void);
int send(uint8_t* buf, size_t size);
int connect(void);
void close(void);


typedef enum{
	Stage_Init = 0,
	Stage_InitDone,
	Stage_GSMDone,
	Stage_GPRSDone,
	Stage_Connected,
	State_SendPending,	
	Stage_Idle
}Stage;

/**@brief  App初始化
 * 
 *
 * @param
 * @return
 * @note
 */
void initApp()
{	
	OSInit();
		
	SemUsart1Rx  = OSSemCreate(0);
	
	/** 创建任务 */
	OSTaskCreate(	ATHandler,
					(void*)0,
					&ATHandlerTaskStk[TASK_STK_SIZE_ATHandler -1],
					TASK_PRIO_ATHandler
				);	
    
//	OSTaskCreate(	AcquireTask,
//					(void*)0,
//					&AcquireTaskStk[TASK_STK_SIZE_Acquire -1],
//					TASK_PRIO_Acquire
//				);
					
					
	OSStart();					
}



void AcquireTask(void* arg)
{
		while(1)
		{
			Debug("Acquire task alive...");
			OSTimeDlyHMSM(0, 0, 5, 0);
		}
}



void ATHandler(void* arg)
{
	INT8U err;
	
	Stage stage  = Stage_Init;

	
	M26_Disable();
	OSTimeDlyHMSM(0, 0, 1, 5);
	M26_Enable();
	OSTimeDlyHMSM(0, 0, 1, 0);
	setConfiguration();
	stage  = Stage_InitDone;
	OSTimeDlyHMSM(0, 0, 5, 0);
	while(1)
	{
		switch(stage){
			case Stage_Init:
//				Debug("State_Init");				
				stage  = Stage_InitDone;				
				break;
			
			case Stage_InitDone:
//				Debug("State_InitDoen");
				if( configGSM() ){
					stage  = Stage_GSMDone;
				}
				else{
//					Debug("configGSM failed");
					OSTimeDlyHMSM(0, 0, 1, 0);
				}
				break;
			
			case Stage_GSMDone:
//				Debug("Stage_GSMDone");
				if( configGPRS() ){
					stage  = Stage_GPRSDone;
				}
				else{
//					Debug("configGPRS failed");
					OSTimeDlyHMSM(0, 0, 1, 0);
				}
				break;
				
			case Stage_Connected:
//				Debug("Stage_Connected");
				if( connect() ){
					stage  = Stage_Idle;
				}
				else{
					Debug("connect failed");
				}
				break;
				
			
				
			default:
				Debug("Stage idle");
				OSTimeDlyHMSM(0, 0, 3, 0);
				
				break;
		}
		
		//Debug("task alive...");
	}
}



void setConfiguration()
{
//	sendAtCmd("AT");
//	OSTimeDlyHMSM(0, 0, 0, 300);
	
	sendAtCmd("ATE0");
	OSTimeDlyHMSM(0, 0, 0, 300);
	
	sendAtCmd("AT+QIURC=0");
	OSTimeDlyHMSM(0, 0, 0, 300);
	
	sendAtCmd("ATQ0");
	OSTimeDlyHMSM(0, 0, 0, 300);
	
	sendAtCmd("ATV0");
	OSTimeDlyHMSM(0, 0, 0, 300);
	
	sendAtCmd("AT+QIHEAD=1");
	OSTimeDlyHMSM(0, 0, 5, 300);	
}





int queryGSM(int *n, int *stat)
{
	INT8U err;
	
	sendAtCmd("AT_CREG?");
	
	OSSemPend(SemUsart1Rx, 30, &err);
	if(err == OS_NO_ERR)
	{
		if(sscanf(Usart1_RxBuf, "+CREG: %d,%d\r\n0") == 2)
		{
			return 1;
		}
	}
	
	return 0;
}


int queryGPRS(int* stat)
{
	INT8U err;
	
	sendAtCmd("AT_CGATT?");
	
	OSSemPend(SemUsart1Rx, 30, &err);
	
	if(err == OS_NO_ERR)
	{
		if(sscanf(Usart1_RxBuf, "+CGATT: %d\r\n0", stat) == 1)
		{
			return 1;
		}
	}
	
	return 0;
}


int  configGSM()
{
	INT8U err;
	
	int n,stat;
	
	sendAtCmd("AT+CREG=1");
	OSSemPend(SemUsart1Rx, 30, &err);
	if(err != OS_NO_ERR){
		return 0;
	}
	
	if(Usart1_RxBuf[0] != '0'){
		return 0;
	}
	
	
	sendAtCmd("AT+CREG?");	
	OSSemPend(SemUsart1Rx, 30, &err);
	
	if(err != OS_NO_ERR)
	{
		return 0;
	}
	
	if(sscanf(Usart1_RxBuf, "+CREG: %d,%d\r\n0", &n, &stat) != 2)
	{
		return 0;
	}
	
	
	if(n > 0  &&  (n == 1 || n == 5))
	{
		return 1;
	}
	
	return 0;
}




int configGPRS()
{
	INT8U err;
	int n, stat;
	
/** Config CGATT */	
	sendAtCmd("AT+CGATT=1");
	OSSemPend(SemUsart1Rx, 30, &err);
	
	
	if(err != OS_NO_ERR){
		return 0;
	}
	
	if(Usart1_RxBuf[0] != '0')
		return 0;
	
/** If configuration ok ,Query CGATT values */	
	sendAtCmd("AT+CGATT?");
	OSSemPend(SemUsart1Rx , 30, &err);
	if(err != OS_NO_ERR){
		return 0;
	}
	
	if(sscanf(Usart1_RxBuf, "+CGATT: %d\r\n0", &stat) != 1){
		return 0;
	}
	
	if(stat != 1){
		return 0;
	}
	
	
/** CGATT ok ,config CGREG  */	
	sendAtCmd("AT+CGREG=1");
	OSSemPend(SemUsart1Rx, 30, &err);
	if(err != OS_NO_ERR){
		return 0;
	}
	
	if(Usart1_RxBuf[0] != '0'){
		return 0;
	}
	
	
/** If config CGREG ok, query CGREG value */		
	sendAtCmd("AT+CGREG?");
	OSSemPend(SemUsart1Rx, 30, &err);
	if(err != OS_NO_ERR){
		return 0;
	}
	
	if( sscanf(Usart1_RxBuf, "+CGREG: %d,%d\r\n0", &n, &stat) != 2){
		return 0;
	}
	
	/** Query value ok */
	if(n == 1  && (stat == 1  ||  stat  == 5) ){
		return 1;
	}
	
	return 0;
}



int connect()
{
	INT8U err;
	
	sendAtCmd("AT+QIOPEN=\"UDP\",\"112.5.80.117\",\"5683\"");
	OSSemPend(SemUsart1Rx, 30, &err);
	if(err != OS_NO_ERR){
		return 0;
	}
	
	if(Usart1_RxBuf[0] != '0'){
		return 0;
	}
	
	sendAtCmd("AT+QISTAT");
	OSSemPend(SemUsart1Rx, 30, &err);
	if(err != OS_NO_ERR){
		return 0;
	}
	
	if(Usart1_RxBuf[0] == 0  &&  Usart1_RxBuf[1] == 8){
		return 1;
	}
	
	return 0;
}



int send(uint8_t* buf, size_t size)
{
	char cmd[16];
	INT8U err;
	
	sprintf(cmd, "AT+QISEND=%d", size);
	sendAtCmd(cmd);
	OSSemPend(SemUsart1Rx, 30, &err);
	
	sendAtData(buf, size);
	
	OSSemPend(SemUsart1Rx, 30, &err);
	if(err != OS_NO_ERR){
		return 0;
	}
	
	if(strstr(Usart1_RxBuf, "SEND OK")){
		return 1;
	}
	
	return 0;
}


void close()
{
	sendAtCmd("AT+QICLOSE");
}


#endif





/** @} */

